package pipelineMiddleWare

import (
	"encoding/binary"
	"fmt"
	"io"
	"math/rand"
	"sort"

	"time"
)

var starttime time.Time //构建时间

func Init() { //将init  改成Init 不然系统初始化 ，手动
	starttime = time.Now() //初始化
}

//统计耗时
func UseTime() {
	fmt.Println(time.Since(starttime)) //统计耗时
}

//数组压入到管道中
func ArraySource(num ...int) <-chan int {

	// fmt.Println(num)

	var out = make(chan int)

	go func() {
		//fmt.Println(num)

		for _, v := range num {
			//fmt.Println(v)

			out <- v

		}
		close(out)
	}()

	return out
}

// 内存排序
func InMemorySort(in <-chan int) <-chan int {
	out := make(chan int, 1024) // 临时管道 管道是引用地址

	go func() {
		data := []int{} //定义一个数组切片
		for v := range in {
			data = append(data, v)
		}

		fmt.Println("数据读取完成", time.Since(starttime))

		sort.Ints(data)

		for _, v := range data {
			out <- v
		}

		close(out)

	}()

	return out
}

//合并,两个管道的数据有序，归并有序的数据压入到另外一个管道
func Merge(ch1, ch2 <-chan int) <-chan int {

	out := make(chan int, 1024)

	go func() {
		fmt.Println("归并开始")
		v1, ok1 := <-ch1
		v2, ok2 := <-ch2

		for ok1 || ok2 {
			if !ok2 || (ok1 && v1 <= v2) {
				out <- v1
				v1, ok1 = <-ch1
			} else {
				out <- v2
				v2, ok2 = <-ch2
			}
		}
		fmt.Println("归并排序结束")
		close(out)

	}()

	return out
}

//多路合并
func MergeN(inputs ...<-chan int) <-chan int {
	if len(inputs) == 1 {
		return inputs[0]
	} else {
		mid := len(inputs) / 2
		fmt.Println("多路合并")
		return Merge(MergeN(inputs[:mid]...), MergeN(inputs[mid:]...))
	}
}

// 随机生产数组
func RandomSource(count int) <-chan int {
	out := make(chan int, count)

	go func() {
		for i := 0; i < count; i++ {
			out <- rand.Intn(100000)
		}

		close(out)
	}()

	return out
}

func WriterSlink(writer io.Writer, in <-chan int) {

	for v := range in {
		buf := make([]byte, 8)

		// str := strconv.Itoa(v)

		binary.BigEndian.PutUint64(buf, uint64(v)) //字节转换

		writer.Write(buf)

		//writer.WriteString(str)
		// WriteString(writer, str)
	}
}

// 读取文件
func ReaderSource(reader io.Reader, chunksize int) <-chan int {

	out := make(chan int, 1024)

	go func() {
		buf := make([]byte, 8) // 64位
		readsize := 0
		for {
			n, err := reader.Read(buf)
			if n > 0 { //读出数据压入
				readsize++
				out <- int(binary.BigEndian.Uint64(buf))
			}
			if err != nil || (chunksize != -1 && readsize >= chunksize) {
				break
			}
		}
		close(out)

	}()
	return out
}
